package com.tomshushu.doc.freedoc.modular.doc.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tomshushu.doc.freedoc.core.exception.ServiceException;
import com.tomshushu.doc.freedoc.modular.directory.entity.DirectoryEntity;
import com.tomshushu.doc.freedoc.modular.directory.mapper.DirectoryMapper;
import com.tomshushu.doc.freedoc.modular.directory.model.param.ReNameParam;
import com.tomshushu.doc.freedoc.modular.directory.service.DirectoryService;
import com.tomshushu.doc.freedoc.modular.doc.entity.DocEntity;
import com.tomshushu.doc.freedoc.modular.doc.mapper.DocMapper;
import com.tomshushu.doc.freedoc.modular.doc.model.param.*;
import com.tomshushu.doc.freedoc.modular.doc.model.result.ListDocResult;
import com.tomshushu.doc.freedoc.modular.doc.model.result.SearchDocResult;
import com.tomshushu.doc.freedoc.modular.doc.service.DocService;
import com.tomshushu.doc.freedoc.modular.user.entity.UserEntity;
import com.tomshushu.doc.freedoc.modular.user.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @description:
 * @author: zhouhong
 * @date: 2025-06-10 17:15
 * @version: 1.0
 */
@Service
public class DocServiceImpl extends ServiceImpl<DocMapper, DocEntity> implements DocService {

    @Resource
    private DocMapper docMapper;
    @Resource
    private DirectoryMapper directoryMapper;
    @Resource
    private UserService userService;

    @Override
    public DocEntity addDoc(AddDocParam param) {
        String userId = StpUtil.getLoginIdAsString();
        DocEntity doc = new DocEntity();
        BeanUtil.copyProperties(param, doc);
        doc.setCreateUser(userId);
        doc.setCreateTime(new java.util.Date());
        this.save(doc);
        return doc;
    }

    @Override
    public void editDoc(EditDocParam param) {
        DocEntity doc = this.getById(param.getDocId());
        if (ObjectUtil.isNotNull(doc)) {
            BeanUtil.copyProperties(param, doc);
            this.updateById(doc);
        }
    }

    public void renameDoc(@RequestBody RenameParam param) {
        DocEntity doc = this.getById(param.getDocId());
        if (ObjectUtil.isNotNull(doc)) {
            doc.setDocTitle(param.getDocTitle());
            this.updateById(doc);
        }
    }

    @Override
    public DocEntity getById(DeleteDocParam param) {
        DocEntity doc = this.getById(param.getDocId());
        UserEntity user =  userService.getById(doc.getCreateUser());
        doc.setCreateUser(user.getUserName());
        return doc;
    }

    @Override
    public void deleteDoc(DeleteDocParam param) {
        this.removeById(param.getDocId());
    }

    @Override
    public List<ListDocResult> listAllChildDoc(ListDocParam param) {
        if (param.getTeamId() == null || param.getProjectId() == null) {
            throw new ServiceException("参数错误");
        }
        if (param.getDirectoryId() != null) {
            List<ListDocResult> result = new ArrayList<>();
            if (param.getIsAll()) {
                // 获取所有子目录
                Set<String> directoryIds = new HashSet<>();
                Set<String> childDirIds = getAllChildDirIdsRecursive(param.getDirectoryId(), directoryIds);
                directoryIds.addAll(childDirIds);
                directoryIds.add(param.getDirectoryId());
                List<DocEntity> entityList = this.list(new LambdaQueryWrapper<DocEntity>()
                        .eq(DocEntity::getTeamId, param.getTeamId())
                        .eq(DocEntity::getProjectId, param.getProjectId())
                        .in(DocEntity::getDirectoryId, directoryIds));
                if (!entityList.isEmpty()) {
                    entityList.forEach(entity -> {
                        ListDocResult listDocResult = new ListDocResult();
                        BeanUtil.copyProperties(entity, listDocResult);
                        result.add(listDocResult);
                    });
                }
            } else {
                // 仅仅获取子目录文档
                List<DocEntity> entityList = this.list(new LambdaQueryWrapper<DocEntity>()
                        .eq(DocEntity::getTeamId, param.getTeamId())
                        .eq(DocEntity::getProjectId, param.getProjectId())
                        .eq(DocEntity::getDirectoryId, param.getDirectoryId()));
                if (!entityList.isEmpty()) {
                    entityList.forEach(entity -> {
                        ListDocResult listDocResult = new ListDocResult();
                        BeanUtil.copyProperties(entity, listDocResult);
                        result.add(listDocResult);
                    });
                }
            }
            return result;
        } else {
            List<ListDocResult> result = new ArrayList<>();
            List<DocEntity> entityList = this.list(new LambdaQueryWrapper<DocEntity>()
                    .eq(DocEntity::getTeamId, param.getTeamId())
                    .eq(DocEntity::getProjectId, param.getProjectId()));

            if (!entityList.isEmpty()) {
                entityList.forEach(entity -> {
                    ListDocResult listDocResult = new ListDocResult();
                    BeanUtil.copyProperties(entity, listDocResult);
                    result.add(listDocResult);
                });
            }
            return result;
        }
    }

    /**
     * 递归获取当前目录及其所有子目录的 ID 集合（含嵌套子目录）
     * @param currentDirId 当前目录 ID
     * @param visited 已访问的目录 ID 集合（防循环）
     * @return 所有子目录 ID 集合（包括当前目录的直接/间接子目录）
     */
    public Set<String> getAllChildDirIdsRecursive(String currentDirId, Set<String> visited) {
        // 防止重复处理同一目录（避免循环引用）
        if (visited.contains(currentDirId)) {
            return new HashSet<>();
        }
        visited.add(currentDirId);
        // 获取当前目录的直接子目录 ID 列表
        List<String> directChildIds = directoryMapper.getAllChildDirectoryIds(currentDirId);
        // 结果集合（包含当前目录的所有子目录）
        Set<String> allChildIds = new HashSet<>(directChildIds);
        // 递归获取每个子目录的子目录，并合并到结果中
        for (String childDirId : directChildIds) {
            Set<String> subChildIds = getAllChildDirIdsRecursive(childDirId, visited);
            allChildIds.addAll(subChildIds);
        }
        return allChildIds;
    }

    @Override
    public List<SearchDocResult> listSearch20Doc(SearchDocParam param) {
        if (param.getTeamId() == null || param.getProjectId() == null || param.getSearchValue() == null) {
            throw new ServiceException("参数错误");
        }
        return docMapper.listSearchDoc(param.getTeamId(), param.getProjectId(),
                param.getSearchValue());
    }

}